package com.hefan.api.controller.H5;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.cat.common.entity.ResultBean;
import com.cat.common.entity.ResultPojo;
import com.cat.common.meta.ResultCode;
import com.cat.tiger.util.GlobalConstants;
import com.hefan.api.service.UserLocalService;
import com.hefan.api.service.live.*;
import com.hefan.api.util.DateTimeUtils;
import com.hefan.common.util.DateUtils;
import com.hefan.common.util.DynamicProperties;
import com.hefan.common.util.HttpUtils;
import com.hefan.common.util.MapUtils;
import com.hefan.live.bean.*;
import com.hefan.live.itf.LiveImOptService;
import com.hefan.live.itf.LiveLogService;
import com.hefan.live.itf.LivingRedisOptService;
import com.hefan.live.itf.RoomEnterExitOptService;
import com.hefan.user.bean.WebUser;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 直播间操作
 *
 * @author kevin_zhang
 */
@Controller
@RequestMapping("/v1/h5")
public class H5LiveController {
    @SuppressWarnings("unused")
    private Logger logger = LoggerFactory.getLogger(H5LiveController.class);

    @Reference
    RoomEnterExitOptService roomEnterExitOptService;
    @Resource
    LiveRoomLocalService liveRoomLocalService;
    @Resource
    LivingLocalService livingLocalService;
    @Resource
    UserLocalService userLocalService;
    @Resource
    LiveLogLocalService liveLogLocalService;
    @Reference
    LiveLogService liveLogServicee;
    @Reference
    LivingRedisOptService livingRedisOptService;
    @Resource
    RoomOptLocalService roomOptLocalService;
    @Resource
    LiveImOptLocalService liveImOptLocalService;

    /**
     * VIP开直播间
     * @param req
     * @return
     */
    @RequestMapping(value = "/openLiving")
    @ResponseBody
    public String openLiving(HttpServletRequest req) {
        ResultPojo result = new ResultPojo(ResultCode.SUCCESS);
        try {
            LiveVo liveVo = HttpUtils.initParam(req, LiveVo.class);
            //验参
            if( null == liveVo || StringUtils.isBlank(liveVo.getUserId()) ||
                    StringUtils.isBlank(liveVo.getLiveName()) ||
                    StringUtils.isBlank(liveVo.getDisplayGraph()) ||
                    StringUtils.isBlank(liveVo.getLiveImg())){
                logger.info("VIP开播，参数错误userId:{}，liveName:{}，DisplayGraph");
                return JSON.toJSONString(new ResultPojo(ResultCode.ParamException));
            }
            WebUser user = userLocalService.getWebUserByUserId(liveVo.getUserId());
            //用户不存在
            if (null == user) {
                return JSON.toJSONString(new ResultPojo(ResultCode.LoginUserIsNotExist));
            }
            // 处理开播账号在其他直播间的问题
            List liveLogPersonsList = roomEnterExitOptService.enterLiveRoomCheck(liveVo.getUserId());
            if (liveLogPersonsList.size() > 0) {
                return JSON.toJSONString(new ResultPojo(ResultCode.LiveRoomRepeat, liveLogPersonsList));
            }
            LiveRoom findRoom = liveRoomLocalService.getLiveRoomByUserId(liveVo.getUserId());
            LiveLog liveLog = new LiveLog();
            LiveRoom liveRoom = new LiveRoom();
            Timestamp now_ = new Timestamp(new Date().getTime());
            Map<String, Object> dataMap = new HashMap<String, Object>();
            // 直播间信息不存在，参数有误
            if (null == findRoom) {
                return JSON.toJSONString(new ResultPojo(ResultCode.ParamException));
            }
            // 主播被禁播
            if (findRoom.getStuff() == GlobalConstants.AUTHOR_LOCK) {
                return JSON.toJSONString(new ResultPojo(ResultCode.LiveIsBanned));
            }
            // 主播正在直播
            if (findRoom.getStatus() == GlobalConstants.AUTHOR_LIVING) {
                return JSON.toJSONString(new ResultPojo(ResultCode.LiveIsLiveing));
            }
            //清理历史观众及机器人信息
            livingLocalService.endLiveClearNoAsync(liveVo.getUserId());

            // 直播开始进行初始化记录操作
            liveRoom.setUserId(liveVo.getUserId());
            liveRoom.setChatRoomId(findRoom.getChatRoomId());
            liveRoom.setStatus(GlobalConstants.AUTHOR_LIVING);
            liveRoom.setLiveName(liveVo.getLiveName());
            liveRoom.setLiveImg(liveVo.getLiveImg());
            liveRoom.setLocation(StringUtils.isBlank(liveVo.getLocation()) ? GlobalConstants.DEFAULT_LOCATION : liveVo.getLocation());
            liveRoom.setStartTime(now_);// 冗余最新直播时间，用于其他地方做排序
            liveRoom.setType(user.getUserType());//冗余主播的类型，用户热门排序

            liveLog.setUserId(liveVo.getUserId());
            liveLog.setChatRoomId(findRoom.getChatRoomId());
            liveLog.setLocation(StringUtils.isBlank(liveVo.getLocation()) ? GlobalConstants.DEFAULT_LOCATION : liveVo.getLocation());
            liveLog.setStartTime(now_);
            liveLog.setDisplayGraph(liveVo.getDisplayGraph());
            liveLog.setLiveName(liveVo.getLiveName());
            liveLog.setLiveImg(liveVo.getLiveImg());
            //新增字段
            liveLog.setIsVipLive(1);
            liveLog.setIsShow(0);
            liveLog.setIsLandscape(liveVo.getIsLandscape());

            //拼接推拉流地址
            String pushPre = DynamicProperties.getString("ali.push.domain.pre");
            String pushSuf = DynamicProperties.getString("ali.push.domain.suf");
            String pull = DynamicProperties.getString("ali.pull.domain");

            if (liveVo.getIsLandscape() == 0) {//竖屏
                liveLog.setLiveUuid(liveLog.getUserId() + "hefan" + DateTimeUtils.getYmdhms() + "_0");
            } else {//横屏
                liveLog.setLiveUuid(liveLog.getUserId() + "hefan" + DateTimeUtils.getYmdhms() + "_1");
            }
            liveRoom.setLiveUuid(liveLog.getLiveUuid());
            liveLog.setLiveUrl( pushPre + liveLog.getLiveUuid() + pushSuf);
            liveLog.setPullUrl( pull + liveLog.getLiveUuid());

            //多套推拉流地址
            Map urlsMap = liveLogLocalService.getLiveUrls(liveLog.getLiveUuid());
            String pullUrls = MapUtils.getStrValue(urlsMap, "pullUrls", "");
            String pushUrls = MapUtils.getStrValue(urlsMap, "pushUrls", "");

            //成功开播后返回的数据信息
            dataMap.put("liveUuid", liveLog.getLiveUuid());
            dataMap.put("liveUrl", liveLog.getLiveUrl());
            dataMap.put("pullUrl", liveLog.getPullUrl());
            dataMap.put("displayGraph", liveLog.getDisplayGraph());
            dataMap.put("hefanTotal", String.valueOf(user.getHefanTotal()));// 主播盒饭数
            dataMap.put("pushUrls",pushUrls);
            dataMap.put("pullUrls",pullUrls);

            // redis中维护在播的直播信息,
            LivingRoomInfoVo lriVo = new LivingRoomInfoVo();
            lriVo.setHeadImg(user.getHeadImg());// 主播头像
            lriVo.setLiveUuid(liveLog.getLiveUuid());// 直播uuid
            lriVo.setName(user.getNickName());// 主播昵称
            lriVo.setChatRoomId(findRoom.getChatRoomId());// 聊天室id
            lriVo.setLiveUrl(liveLog.getPullUrl());// 拉流地址
            lriVo.setPersonSign(liveVo.getLiveName());// 直播名
            lriVo.setId(liveVo.getUserId());// 主播id
            lriVo.setUserId(liveVo.getUserId());// 主播id
            lriVo.setType(user.getUserType());// 主播类型
            lriVo.setLiveImg(liveVo.getLiveImg());// 直播间封面
            lriVo.setDisplayGraph(liveLog.getDisplayGraph());// 点亮样式
            lriVo.setLocation(StringUtils.isNotBlank(liveLog.getLocation()) ? liveLog.getLocation():GlobalConstants.DEFAULT_LOCATION);
            lriVo.setHefanTotal(String.valueOf(user.getHefanTotal()));//主播盒饭数
            lriVo.setPullUrls(pullUrls);//拉流地址
            lriVo.setPushUrls(pushUrls);//推流地址
            lriVo.setStartLiveTime(System.currentTimeMillis());//开播时间，用于列表排序
            //新增字段VIP
            lriVo.setIsShow(0);
            lriVo.setIsVipLive(1);
            lriVo.setDoubleSrc(1);
            lriVo.setRotate(1);
            lriVo.setIsLandscape(liveVo.getIsLandscape());
            if ( !liveLogLocalService.liveStartOperate(liveRoom, liveLog)) {
                logger.info("VIP开播，liveRoom，liveLog入库DB处理失败");
                return JSON.toJSONString(new ResultPojo(ResultCode.UNSUCCESS));
            }
            logger.info("VIP开播：更新live_room直播状态和插入live_log直播数据成功");
            livingRedisOptService.addLivingInfo_Hash(liveVo.getUserId(), JSON.toJSONString(lriVo));
            if (!livingRedisOptService.isExistsLivingInfo_Hash(liveVo.getUserId())){
                logger.info("VIP开播：直播间信息存入redis失败");
                return JSON.toJSONString(new ResultPojo(ResultCode.UNSUCCESS));
            }
            logger.info("VIP开播：在redis中存入直播信息成功");

            //更新最新、热门列表页静态文件 异步
            livingLocalService.liveStartOpt();
            logger.info("VIP开播：异步执行更新直播列表文件");
            //开播时机器人进入直播间 更新peopleCount文件  发送IM更新用户列表  异步  ---- VIP不需要
//            livingLocalService.addRobotWhenStart(liveLog.getLiveUuid(),liveLog.getChatRoomId(),liveVo.getUserId());
            logger.info("VIP开播：异步执行，加入机器人、更新人数文件、发送更新观众列表IM消息");

            return JSON.toJSONString(new ResultBean(ResultCode.SUCCESS, dataMap));
        } catch (Exception e) {
            e.printStackTrace();
            return JSON.toJSONString(new ResultPojo(ResultCode.UNSUCCESS));
        }
    }

    /**
     * VIP关直播间
     * @param req
     * @return
     */
    @RequestMapping(value = "/closeLiving")
    @ResponseBody
    public String closeLiving(HttpServletRequest req) {
        try {
            LiveVo liveVo = HttpUtils.initParam(req, LiveVo.class);
            // 参数异常
            if (null == liveVo || StringUtils.isBlank(liveVo.getUserId())
                    || StringUtils.isBlank(liveVo.getLiveUuid())) {
                return JSON.toJSONString(new ResultPojo(ResultCode.ParamException));
            }
            Timestamp now_ = new Timestamp(new Date().getTime());
            Map<String, Object> dataMap = new HashMap<String, Object>();
            LiveRoom liveRoom = liveRoomLocalService.getLiveRoomByUserId(liveVo.getUserId());
            // 直播已经关闭或不存在
            if (null == liveRoom || liveRoom.getStatus() == GlobalConstants.AUTHOR_LIVEEND) {
                logger.info("VIP直播：直播已经关闭或不存在");
                return JSON.toJSONString(new ResultPojo(ResultCode.LiveIsClose));
            }
            WebUser user = userLocalService.getWebUserByUserId(liveVo.getUserId());
            if (null == user) {
                logger.info("VIP直播：user不存在");
                return JSON.toJSONString(new ResultPojo(ResultCode.ParamException));
            }
            // 获取用户直播信息
            LiveLog liveLog_ = liveLogLocalService.getLiveLogByUuid(liveVo.getLiveUuid());
            if (null == liveLog_) {
                return JSON.toJSONString(new ResultPojo(ResultCode.ParamException));
            }
            if (!liveLog_.getUserId().equals(liveVo.getUserId())) {
                return JSON.toJSONString(new ResultPojo(ResultCode.AuthError));
            }
            liveLog_.setEndTime(now_);
            // 闭环当次直播数据
            long num = liveLog_.getWatchNum();
            try {
                String watchNum = livingRedisOptService.getLivingWatchNum(liveLog_.getLiveUuid());
                if (StringUtils.isNotBlank(watchNum)) {
                    num = Long.valueOf(watchNum);
                    liveLog_.setWatchNum(num);
                }
            } catch (Exception e) {
            }
            //更新live_room直播状态，更新live_log中结束时间人数收入等
            liveLog_ = liveLogLocalService.liveEndOperate(liveLog_);
            if (null == liveLog_) {
                return JSON.toJSONString(new ResultPojo(ResultCode.UNSUCCESS));
            }
            long ticketCount = livingRedisOptService.getTicketCountByUuid(liveVo.getLiveUuid());
            dataMap.put("ticketCount", ticketCount);
            dataMap.put("watchNum", num);
            dataMap.put("liveLength", liveLog_.getLiveLength());

            // 明星片场分享动态
            if (user.getUserType() == GlobalConstants.USER_TYPE_STAR || user.getUserType() == GlobalConstants.USER_TYPE_SITE) {
                if (liveLog_.getLiveLength() > 120) { // 两分钟以上才分享
                    String pre = DynamicProperties.getString("replay.domain.pre");
                    String suf = DynamicProperties.getString("replay.domain.suf");
                    LiveDynamicVo liveDynamicVo = new LiveDynamicVo();
                    liveDynamicVo.setUserId(liveVo.getUserId());
                    liveDynamicVo.setBackImg(liveRoom.getLiveImg());
                    liveDynamicVo.setFromType("0");// 来源
                    liveDynamicVo.setIsSync(1);// 是否同步到视频
                    liveDynamicVo.setLength(DateUtils.getHms(liveLog_.getLiveLength() * 1000));
                    liveDynamicVo.setMessageInfo(liveLog_.getLiveName());// 动态文字
                    liveDynamicVo.setPathTrans(pre +  liveLog_.getLiveUuid() + suf);// 拉流地址
                    liveDynamicVo.setTranscode(true);// 是否转码
                    liveDynamicVo.setMessageType("3");// 3表示动态类型是视频
                    liveDynamicVo.setTimes(liveLog_.getWatchNum());
                    roomOptLocalService.shareLive(liveDynamicVo);
                }
            }
            //异步发送IM消息,发送三次
            liveImOptLocalService.sendImMessage(user, liveLog_.getChatRoomId(), liveVo.getLiveUuid(),String.valueOf(num),
                    String.valueOf(liveLog_.getLiveLength()),String.valueOf(liveLog_.getTicketCount()));
            //异步执行:同步历史盒饭数到web_user中
            userLocalService.incrWebUserHefanFromCach(user.getUserId());
            logger.info("VIP关播处理完成");
            return JSON.toJSONString(new ResultBean(ResultCode.SUCCESS, dataMap));
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("VIP关播失败");
            return JSON.toJSONString(new ResultPojo(ResultCode.UNSUCCESS));
        }
    }

    /**
     * 获取VIP直播列表
     *
     * @param req
     * @return
     */
    @RequestMapping(value = "/getVIPLivingList")
    @ResponseBody
    public String getVIPLivingList(HttpServletRequest req) {
        ResultBean resultBean = new ResultBean(ResultCode.SUCCESS);
        List<LivingRoomInfoVo> livingRoomList = roomEnterExitOptService.getALLVIPLivingRoomInfoList();
        resultBean.setData(livingRoomList);
        return JSON.toJSONString(resultBean);
    }

    /**
     * 显示/隐藏直播间
     *
     * @param req
     * @return
     */
    @RequestMapping(value = "/displayOrHideLiving")
    @ResponseBody
    public String displayOrHideLiving(HttpServletRequest req) {
        ResultBean resultBean = new ResultBean(ResultCode.SUCCESS);
        Map<String, Object> map = HttpUtils.initParam(req, Map.class);
        if (null == map || map.isEmpty()) {
            resultBean.setCode(ResultCode.ParamException.get_code());
            resultBean.setMsg(ResultCode.ParamException.getMsg());
            return JSON.toJSONString(resultBean);
        }
        String authId = MapUtils.getStrValue(map, "authId", "");
        int isShow = MapUtils.getIntValue(map, "isShow", 0);
        if (StringUtils.isBlank(authId) || isShow < 0) {
            resultBean.setCode(ResultCode.ParamException.get_code());
            resultBean.setMsg(ResultCode.ParamException.getMsg());
            return JSON.toJSONString(resultBean);
        }

        LivingRoomInfoVo livingRoomInfoVo = roomEnterExitOptService.getLivingRoomInfoByAuthId(authId);
        if (null == livingRoomInfoVo)
            return JSON.toJSONString(new ResultBean(ResultCode.LiveIsNull));
        if (livingRoomInfoVo.getIsShow() != isShow) {
            if (isShow == 1)
                livingRoomInfoVo.setIsShow(1);
            else
                livingRoomInfoVo.setIsShow(0);
            return JSON.toJSONString(liveLogServicee.updateVIPLiveStatus(livingRoomInfoVo));
        }
        return JSON.toJSONString(resultBean);
    }
}
